package com.sevenstudio.adu.gasing.engine;

import org.andengine.engine.camera.Camera;
import org.andengine.engine.handler.IUpdateHandler;
import org.andengine.engine.handler.timer.ITimerCallback;
import org.andengine.engine.handler.timer.TimerHandler;
import org.andengine.engine.options.EngineOptions;
import org.andengine.engine.options.ScreenOrientation;
import org.andengine.engine.options.resolutionpolicy.RatioResolutionPolicy;
import org.andengine.entity.modifier.MoveModifier;
import org.andengine.entity.modifier.RotationByModifier;
import org.andengine.entity.scene.IOnAreaTouchListener;
import org.andengine.entity.scene.IOnSceneTouchListener;
import org.andengine.entity.scene.Scene;
import org.andengine.entity.sprite.Sprite;
import org.andengine.input.touch.detector.ClickDetector;
import org.andengine.input.touch.detector.ClickDetector.IClickDetectorListener;
import org.andengine.input.touch.detector.ScrollDetector;
import org.andengine.input.touch.detector.ScrollDetector.IScrollDetectorListener;
import org.andengine.ui.activity.SimpleBaseGameActivity;

import android.content.Intent;
import android.os.Handler;
import android.view.KeyEvent;
import android.widget.Toast;

import com.sevenstudio.adu.gasing.bluetooth.BT_Server_Client;
import com.sevenstudio.adu.gasing.define.iGameDefines;
import com.sevenstudio.adu.gasing.element.AAnimatedSprite;
import com.sevenstudio.adu.gasing.element.ABackground;
import com.sevenstudio.adu.gasing.element.AFont;
import com.sevenstudio.adu.gasing.element.AHud;
import com.sevenstudio.adu.gasing.element.ARectangle;
import com.sevenstudio.adu.gasing.element.AScene;
import com.sevenstudio.adu.gasing.element.ASprite;
import com.sevenstudio.adu.gasing.element.AStrokeText;
import com.sevenstudio.adu.gasing.element.AText;
import com.sevenstudio.adu.gasing.object.Gasing;

public abstract class GameEngine extends SimpleBaseGameActivity implements IUpdateHandler, IOnSceneTouchListener, IClickDetectorListener, IOnAreaTouchListener,
	IScrollDetectorListener
{
	public static float				SCREEN_WIDTH, SCREEN_HEIGHT, CAMERA_WIDTH, CAMERA_HEIGHT;
	public static ScreenOrientation	ORIENTATION;
	
	protected Camera				camera;
	public Scene					mScene			= new Scene();
	protected ClickDetector			mClickDetector	= new ClickDetector(this);
	protected ScrollDetector		mScrollDetector	= new ScrollDetector(this);
	int								gameUpdateStep;
	
	public int						gameCurrentState, gameNextState;
	public int						messageCurrentState, messageNextState;
	
	private long					waitTime, waitTimeElapsed, waitTimeRemaining;
	
	String							TAG_UPDATE		= "AGD_UPDATE";
	String							TAG_STATE		= "AGD_STATE";
	
	public AFont					gameFont[]		= new AFont[iGameDefines.FONT_COUNT];
	
	public final Handler			handler			= new Handler();
	
	AScene							scene;
	
	public static GameEngine		context;
	
	public BT_Server_Client			server_Client;
	
	public EngineOptions onCreateEngineOptions()
	{
		context = this;
		GameInit();
		camera = new Camera(0, 0, CAMERA_WIDTH, CAMERA_HEIGHT);
		EngineOptions engineOptions = new EngineOptions(true, ORIENTATION, new RatioResolutionPolicy(CAMERA_WIDTH, CAMERA_HEIGHT), camera);
		
		engineOptions.getAudioOptions().setNeedsMusic(true).setNeedsSound(true);
		return engineOptions;
		
	}
	
	protected void onCreateResources()
	{
		GameEngine.context.runOnUiThread(new Runnable()
		{
			public void run()
			{
				server_Client = new BT_Server_Client(GameEngine.context);
			}
		});
		mEngine.registerUpdateHandler(this);
		
	}
	
	@Override
	protected Scene onCreateScene()
	{
		LoadAllFont();
		return mScene;
	}
	
	public void onUpdate(float pSecondsElapsed)
	{
		// if(iConfiguration.use_debug_gameUpdate)
		// {
		// Utils.TRACE("gameUpdateStep = "+gameUpdateStep);
		// }
		
		GameUpdate();
	}
	
	public void reset()
	{}
	
	@Override
	public synchronized void onPauseGame()
	{
		super.onPauseGame();
	}
	
	@Override
	public synchronized void onResumeGame()
	{
		super.onResumeGame();
		waitTime = System.currentTimeMillis() + waitTimeRemaining;
	}
	
	public void WaitTimeCapture()
	{
		waitTime = System.currentTimeMillis();
	}
	
	public boolean IsTimePassed(long ms)
	{
		waitTimeElapsed = System.currentTimeMillis() - waitTime;
		waitTimeRemaining = ms - waitTimeElapsed;
		if (waitTime + ms <= System.currentTimeMillis())
		{
			waitTimeElapsed = 0;
			waitTimeRemaining = 0;
			
			return true;
		}
		return false;
	}
	
	public boolean IsCurrentTimeShorterThanCaptured(long ms)
	{
		waitTimeElapsed = System.currentTimeMillis() - waitTime;
		waitTimeRemaining = ms - waitTimeElapsed;
		if (waitTime + ms > System.currentTimeMillis())
		{
			waitTimeElapsed = 0;
			waitTimeRemaining = 0;
			
			return true;
		}
		return false;
	}
	
	public void SetNextMessageState(int message)
	{
		messageNextState = message;
	}
	
	public void SetNextGameState(int message)
	{
		gameNextState = message;
	}
	
	public int NextMessageState()
	{
		int next = messageCurrentState + 1;
		if (next > iGameDefines.MESSAGE_STATE_EXIT) { return iGameDefines.MESSAGE_STATE_INIT; }
		return next;
	}
	
	public int NextGameState()
	{
		return gameCurrentState + 1;
	}
	
	public abstract void GameInit();
	
	public abstract void GameUpdate();
	
	public void SetGameScene(AScene scene)
	{
		this.scene = scene;
		mEngine.setScene(scene.theScene());
	}
	
	public AScene getGameScene()
	{
		return scene;
	}
	
	public void HudAttach(AHud hud, ASprite sprite)
	{
		hud.theHud().attachChild(sprite.theSprite());
	}
	
	public void attachParent(ASprite sprParent, ASprite sprChild)
	{
		sprParent.theSprite().attachChild(sprChild.theSprite());
	}
	
	public void attachParent(ASprite sprParent, AText txt)
	{
		sprParent.theSprite().attachChild(txt.theText());
	}
	
	public void SceneAttach(AScene scene, ASprite sprite)
	{
		scene.theScene().attachChild(sprite.theSprite());
	}
	
	public void SceneAttach(AScene scene, AAnimatedSprite sprite)
	{
		scene.theScene().attachChild(sprite.theSprite());
	}
	
	public void SceneAttach(AScene scene, ABackground sprite)
	{
		scene.theScene().attachChild(sprite.theSprite());
	}
	
	public void SceneAttach(AScene scene, Gasing sprite)
	{
		scene.theScene().attachChild(sprite.getSprite());
	}
	
	public void SceneAttach(AScene scene, AText text)
	{
		scene.theScene().attachChild(text.theText());
	}
	
	public void SceneAttach(AScene scene, AStrokeText text)
	{
		scene.theScene().attachChild(text.theText());
	}
	
	public void SceneAttach(AScene scene, ARectangle rect)
	{
		scene.theScene().attachChild(rect.theRect());
	}
	
	@Override
	public boolean onKeyDown(int keyCode, KeyEvent event)
	{
		return false;
	}
	
	void LoadAllFont()
	{
		for (int i = 0; i < gameFont.length; i++)
		{
			gameFont[i] = new AFont(this, i);
		}
	}
	
	public void exit()
	{
		finish();
	}
	
	public void moveObj(final float pDuration, final float pFromX, final float pToX, final float pFromY, final float pToY, final Sprite sprite)
	{
		// TODO Auto-generated method stub
		TimerHandler handler = new TimerHandler(0.2f, new ITimerCallback()
		{
			
			public void onTimePassed(TimerHandler pTimerHandler)
			{
				// TODO Auto-generated method stub
				
				MoveModifier modifier = new MoveModifier(pDuration, pFromX, pToX, pFromY, pToY);
				sprite.registerEntityModifier(modifier);
				
			}
		});
		
		mEngine.registerUpdateHandler(handler);
	}
	
	public void rotateObj(final ASprite spr, final int plusMin)
	{
		TimerHandler handler = new TimerHandler(0.1f, new ITimerCallback()
		{
			
			public void onTimePassed(TimerHandler pTimerHandler)
			{
				// TODO Auto-generated method stub
				spr.theSprite().registerEntityModifier(new RotationByModifier(0.4f, plusMin * 180));
			}
		});
		
		mEngine.registerUpdateHandler(handler);
	}
	
	public void makeToast(String str, int duration)
	{
		Toast.makeText(this, str, duration).show();
	}
	
	protected void onActivityResult(int requestCode, int resultCode, Intent data)
	{
		server_Client.onActivityResult(requestCode, resultCode, data);
		super.onActivityResult(requestCode, resultCode, data);
	}
}
